

public class Tree<Node, Edge> {
	private Node nodeDesc;
	private Edge edgeDesc;
	private Tree<Node, Edge> firstChild;
	private Tree<Node, Edge> nextSibling;
	
	public Tree(Node nodeDesc) {
		this.nodeDesc = nodeDesc;
		this.edgeDesc = null;
		this.firstChild = null;
		this.nextSibling = null;
	}
	
	private Tree(Node nodeDesc, Edge edgeDesc, Tree<Node, Edge> nextSibling) {
		this.nodeDesc = nodeDesc;
		this.edgeDesc = edgeDesc;
		this.nextSibling = nextSibling;
	}
	
	public Node getNodeDesc() {
		return nodeDesc;
	}
	
	private abstract class TreeIterator<Return> implements TreeIteratorInterface<Return, Node, Edge> {
		private final Tree<Node, Edge> parent;
		protected Tree<Node, Edge> prev;
		protected Tree<Node, Edge> cur;
		
		public TreeIterator(Tree<Node, Edge> parent) {
			this.parent = parent;
			this.prev = null;
			this.cur = firstChild;
		}
		
		public boolean hasNext() {
			return (cur != null);
		}
		
		public void insert(Node node, Edge edge) {
			if (prev == null) { // insert at the begin of the list
				cur = new Tree<Node, Edge>(node, edge, cur);
				parent.firstChild = cur;
			}
			else { // insert
				Tree<Node, Edge> tmp = cur;
				cur = new Tree<Node, Edge>(node, edge, tmp);
				prev.nextSibling = cur;
			}
		}
	}
	
	private class NodeIterator extends TreeIterator<Tree<Node, Edge>> {
		
		public NodeIterator(Tree<Node, Edge> parent) {
			super(parent);
		}
		
		public Tree<Node, Edge> next() {
			prev = cur;
			cur = cur.nextSibling;
			return prev;
		}
	}
	
	private class EdgeIterator extends TreeIterator<Edge> {
		
		public EdgeIterator(Tree<Node, Edge> parent) {
			super(parent);
		}
		
		public Edge next() {
			prev = cur;
			cur = cur.nextSibling;
			return prev.edgeDesc;
		}
	}

	public TreeIteratorInterface<Tree<Node, Edge>, Node, Edge> getNodeIterator() {
		return new NodeIterator(this);
	}
	
	public TreeIteratorInterface<Edge, Node, Edge> getEdgeIterator() {
		return new EdgeIterator(this);
	}
	
}
